執行全域前一刻,做全域的預編譯;執行function前一刻,做function的預編譯。
形參
(形式參數)、變數
(就是指前面有var
let
const
關鍵字,注意此時不賦值)實參
(實際參數)給形參
function
(不管body,執行時才看)function
和變數
這裡才賦值)console.log(fun(12,26,38))
console.log(fun(167,2))
console.log(`a=${a}`)
var a=1;
function fun(a,b,c,d){
e=7;
if(c){}else{c=0}
return `a(${a}),b(${b}),c(${c}),d(${d})e(${e})`
}
console.log(`a=${a}`)
全域執行
前一刻,做全域預編譯
GO是global object 全局作用域
GO{
step1.1 宣告變數 舉例:看到 var a=1,定義a為全域變數,但不賦值
a : undefined,
step1.2 宣告function 注意:宣告function時,不管他的body
fun : function fun(a,b,c,d){......}
}
全域預編譯
結束,執行全域執行
- 看一行 執行一行step2.1 看到console.log(fun(12,26,38))
,執行fun function
console.log(fun(12,26,38))
function fun(a,b,c,d){
e=7;
if(c){}else{c=0}
return `a(${a})+b(${b})+c(${c})+d(${d})`
}
fun function
的前一刻,做fun function區域預編譯
AO是activation object 局部作用域、活躍對象
為甚麼叫活躍對象,是因為function他在跑的時候,AO才存在,function結束,AO消失
step3.1 宣告形參
fun AO{
a : undefined,
b : undefined,
c : undefined,
d : undefined
}
宣告變數 沒有變數宣告
注意:e=7;
前面沒有var
let
const
關鍵字,不是需要宣告的變數
step3.2 賦值:實參給形參
fun AO{
a : 12,
b : 26,
c : 38,
d : undefined
}
step3.3 宣告function fun中沒有function需要宣告
function區域預編譯
結束,執行console.log(fun(12,26,38))
- 看一行 執行一行step4.1 e=7;
變數的前面沒有 var
let
const
,被判定為全域變數
小備註:因為已經在執行階段,所以變數不用先是undefined
再變成7
GO{
a : undefined,
fun : function fun(a,b,c,d){......},
e : 7
}
step4.2 執行完return
,AO銷毀
console.log(fun(167,2))
- 只講不一樣的GO{
a : undefined,
fun : function fun(a,b,c,d){......},
e : 7
}
fun AO{
a : 167,
b : 2,
c : undefined,
d : undefined
}
step5.1 if(c){}else{c=0}
因為undefined
是falsy
,所以跳到else{c=0}
step5.2 fun
執行完,AO銷毀
人肉編譯器們,剩下三行了,加油
console.log(`a=${a}`)
var a=1;
console.log(`a=${a}`)
GO{
a : undefined,
fun : function fun(a,b,c,d){......},
e : 7
}
第一個console.log(
a=${a})
是在「預編譯後,賦值前」,所以a=undefined
第二個console.log(
a=${a})
是在「賦值後」,所以a=1
剛剛的「實戰gogo」,有看到變數的提升和function的提升。我們稍微總結一下 →
原始值
引用值
,會去參照function的body但也不是所有function都會乖乖地提升,那到底是誰怎麼不乖呢?要拜乖乖?